home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / mail / imapperl.6 / imapperl / imap / imapsync < prev    next >
Text File  |  1996-02-04  |  9KB  |  436 lines

  1. #! /usr/bin/perl
  2.  
  3. require "getopts.pl";
  4. require "msg.pl";
  5. require "imap.pl";
  6.  
  7. &Getopts('bde:h:il:np:qrt:u:x');
  8.  
  9. $body = $opt_b;        # retrieve BODY[1] instead of RFC822.TEXT
  10. $debug = $opt_d;    # debug mode
  11. $efficiency = $opt_e;    # efficiency
  12. $host = $opt_h;        # specify IMAP host (localhost)
  13. $important = $opt_i;     # flag retrieved messages as important
  14. $limit = $opt_l;    # only retrieve messages smaller than specified value
  15. $new = $opt_n;        # flag retrieved messages as new
  16. $port = $opt_p;        # specify IMAP port (143)
  17. $quiet = $opt_q;    # quiet mode
  18. $remove = $opt_r;    # delete retrieved messages
  19. $timeout = $opt_t;    # place timeout on reading lines
  20. $user = $opt_u;        # use another name to login
  21. $expunge = $opt_x;    # expunge regularly
  22.  
  23. $host = 'localhost' unless $host;
  24. $port = 143 unless $port;
  25. $user = getpwuid($>) unless $user;
  26. $timeout = 0 unless $timeout;
  27.  
  28. $important = 1 if $new;        # flag as new implies flag as important
  29.  
  30. $efficiency = 10 unless $efficiency > 0;
  31.  
  32. $pid = 0;
  33.  
  34. &msg'level(2) if $debug;
  35. &msg'level(0) if $quiet;
  36.  
  37. if (! defined($ENV{"HOME"}))
  38. {
  39.     &msg'error("HOME not set");
  40.     exit 1;
  41. }
  42. $home = $ENV{"HOME"};
  43.  
  44. if (! open(RC, "$home/.imapsyncrc"))
  45. {
  46.     &msg'error("can not open ~/.imapsyncrc");
  47.     exit 1;
  48. }
  49.  
  50. $numboxes = 0;
  51. while (chop($mbox = <RC>))
  52. {
  53.     if (! $mbox =~ /^\s*$/)
  54.     {
  55.         push(@mailboxes, $mbox);
  56.         $numboxes++;
  57.     }
  58. }
  59.  
  60. close(RC);
  61.  
  62. &msg'msg("$numboxes mailbox: @mailboxes") if ($numboxes == 1);
  63. &msg'msg("$numboxes mailboxes: @mailboxes") if ($numboxes != 1);
  64.  
  65. $totalmsgs = 0;
  66. $totalmsgskips = 0;
  67. $totalmsgerrors = 0;
  68.  
  69. if (! &imap'init(\&message, \&mailbox, \&exists, \&recent, \&expunge, \&flags,
  70.                     \&search, \&fetch))
  71. {
  72.     &msg'error("can not initialize");
  73.     exit 1;
  74. }
  75.  
  76. if (! &imap'open($host, $port))
  77. {
  78.     &msg'error("can not make connection");
  79.     exit 1;
  80. }
  81.  
  82. $tag = &imap'login($user);
  83. ($match, $result, $message) = &imap'loop($tag,$timeout);
  84. if ($result ne "OK")
  85. {
  86.     &msg'error("$message");
  87.     &imap'close();
  88.     exit 1;
  89. }
  90.  
  91. MAILBOX:
  92. foreach $mbox (@mailboxes)
  93. {
  94.     &msg'msg("scanning mailbox $mbox");
  95.  
  96.     $tag = &imap'select($mbox);
  97.     ($match, $result, $message) = &imap'loop($tag,$timeout);
  98.     if ($result ne "OK")
  99.     {
  100.         &msg'error("$message");
  101.         next MAILBOX;
  102.     }
  103.     &msg'msg("$mailbox{$mbox}->{'exists'} messages, $mailbox{$mbox}->{'recent'} recent");
  104.  
  105.     # if ($mailbox{$mbox}->{'recent'} == 0)
  106.     # {
  107.     #     &msg'msg("skipping mailbox");
  108.     #     next MAILBOX;
  109.     # }
  110.  
  111.     $tag = &imap'search("UNSEEN");
  112.  
  113.     # reset some variables in the meantime
  114.     $msgs = 0;
  115.     $msgskips = 0;
  116.     $msgerrors = 0;
  117.  
  118.     ($match, $result, $message) = &imap'loop($tag,$timeout);
  119.     if ($result ne "OK")
  120.     {
  121.         &msg'error("$message");
  122.         &imap'close();
  123.         exit 1;
  124.     }
  125.  
  126.     @seqlist = split(' ', $mailbox{$mbox}->{'search'});
  127.     $seqcount = $#seqlist + 1;
  128.     $seqoffset = 0;
  129.  
  130. FETCH:
  131.     while ($seqcount - $seqoffset > 0)
  132.     {
  133.         if ($seqcount - $seqoffset < $efficiency)
  134.         {
  135.             $seqrange = $seqcount - $seqoffset;
  136.         }
  137.         else
  138.         {
  139.             $seqrange = $efficiency;
  140.         }
  141.  
  142.         @sequence = @seqlist[$seqoffset..($seqoffset+$seqrange-1)];
  143.         $sequence = join(',', @sequence);
  144.  
  145.         $seqoffset = $seqoffset+$seqrange;
  146.  
  147.         $tag = &imap'fetch("$sequence", "ALL");
  148.         ($match, $result, $message) = &imap'loop($tag,$timeout);
  149.         if ($result ne "OK")
  150.         {
  151.             &msg'error("$message");
  152.             &imap'close();
  153.             exit 1;
  154.         }
  155.         foreach $i (0..$#sequence)
  156.         {
  157.             $size = $message{@sequence[$i]}->{'size'};
  158.             if ($size && $limit > 0 && $size > $limit)
  159.             {
  160.                 &msg'warn("skipping message @sequence[$i], $size bytes long");
  161.                 @sequence[$i] = '';
  162.                 $msgskips++;
  163.             }
  164.             else
  165.             {
  166.                 &msg'msg("retrieving message @sequence[$i], $size bytes long");
  167.                 $msgs++;
  168.             }
  169.         }
  170.         $sequence = join(' ', @sequence);
  171.         $sequence =~ s/^\s*(.*)\s*$/$1/;
  172.         @sequence = split(/\s+/, $sequence);
  173.         $sequence = join(',', @sequence);
  174.  
  175.         if (length($sequence) > 0)
  176.         {
  177.             if ($body)
  178.             {
  179.                 $fetch = "(RFC822.HEADER BODY[1])";
  180.             }
  181.             else
  182.             {
  183.                 $fetch = "(RFC822.HEADER RFC822.TEXT)";
  184.             }
  185.             $tag = &imap'fetch("$sequence", "$fetch");
  186.             ($match, $result, $message) = &imap'loop($tag,$timeout);
  187.             if ($result ne "OK")
  188.             {
  189.                 &msg'error("$message");
  190.                 &imap'close();
  191.                 exit 1;
  192.             }
  193.  
  194.             # wait for child process if it is still running
  195.             if ($pid)
  196.             {
  197.                 waitpid($pid, 0);
  198.             }
  199.  
  200.             unless($pid = fork())
  201.             {
  202.                 foreach $i (0..$#sequence)
  203.                 {
  204. # Linux: change this to: open(FORMAIL, "| deliver -A <username>")
  205.                     if (! open(FORMAIL, "| formail -Ys procmail"))
  206.                     {
  207.                         &msg'error("can not pipe to formail");
  208.                         &imap'close();
  209.                         exit 1;
  210.                     }
  211.                     print FORMAIL $message{@sequence[$i]}->{'header'};
  212.                     if ($body)
  213.                     {
  214.                         print FORMAIL $message{@sequence[$i]}->{'body'};
  215.                     }
  216.                     else
  217.                     {
  218.                         print FORMAIL $message{@sequence[$i]}->{'text'};
  219.                     }
  220.                     if (! close(FORMAIL) || $?)
  221.                     {
  222.                         &msg'error("formail failed");
  223.                         &imap'close();
  224.                         exit 1;
  225.                     }
  226.                 }
  227.                 exit 0;
  228.             }
  229.  
  230.             if ($remove || $important)
  231.             {
  232.                 $flags = "\\DELETED" if ($remove);
  233.                 $flags = "\\FLAGGED" if ($important);
  234.                 $tag = &imap'store("$sequence", "+FLAGS", "($flags)");
  235.                 ($match, $result, $message) = &imap'loop($tag,$timeout);
  236.                 if ($result ne "OK")
  237.                 {
  238.                     &msg'error("$message");
  239.                     &imap'close();
  240.                     exit 1;
  241.                 }
  242.                 if ($new)
  243.                 {
  244.                     $tag = &imap'store("$sequence", "-FLAGS", "(\\SEEN)");
  245.                     ($match, $result, $message) = &imap'loop($tag,$timeout);
  246.                     if ($result ne "OK")
  247.                     {
  248.                         &msg'error("$message");
  249.                         &imap'close();
  250.                         exit 1;
  251.                     }
  252.                 }
  253.             }
  254.  
  255.             # expunge messages
  256.             if ($remove && $expunge)
  257.             {
  258.                 $tag = &imap'expunge();
  259.                 ($match, $result, $message) = &imap'loop($tag,$timeout);
  260.                 if ($result ne "OK")
  261.                 {
  262.                     &msg'error("$message");
  263.                     &imap'close();
  264.                     exit 1;
  265.                 }
  266.  
  267.                 # determine message sequence again that is still UNSEEN
  268.                 # it was changed c.q. shifted by the expunge
  269.                 $tag = &imap'search("UNSEEN");
  270.                 ($match, $result, $message) = &imap'loop($tag,$timeout);
  271.                 if ($result ne "OK")
  272.                 {
  273.                     &msg'error("$message");
  274.                     &imap'close();
  275.                     exit 1;
  276.                 }
  277.  
  278.                 @seqlist = split(' ', $mailbox{$mbox}->{'search'});
  279.                 $seqcount = $#seqlist + 1;
  280.                 $seqoffset = $msgskips;
  281.             }
  282.         }
  283.  
  284.         undef %message;
  285.     }
  286.  
  287.     # expunge messages if not already done earlier by regular expunge mode
  288.     if ($remove && $expunge != 1)
  289.     {
  290.         $tag = &imap'expunge();
  291.         ($match, $result, $message) = &imap'loop($tag,$timeout);
  292.         if ($result ne "OK")
  293.         {
  294.             &msg'error("$message");
  295.             &imap'close();
  296.             exit 1;
  297.         }
  298.     }
  299.  
  300.     if ($msgs + $msgskips + $msgerrors > 0)
  301.     {
  302.         &msg'msg("$msgs retrieved, $msgskips skipped, $msgerrors errors");
  303.         $totalmsgs += $msgs;
  304.         $totalmsgskips += $msgskips;
  305.         $totalmsgerrors += $msgerrors;
  306.     }
  307. }
  308.  
  309. $tag = &imap'logout();
  310. ($match, $result, $message) = &imap'loop($tag,$timeout);
  311. if ($result ne "OK")
  312. {
  313.     &msg'error("$message");
  314.     &imap'close();
  315.     exit 1;
  316. }
  317.  
  318. &imap'close();
  319.  
  320. &msg'msg("total: $totalmsgs retrieved, $totalmsgskips skipped, $totalmsgerrors errors");
  321.  
  322. # wait for child process if it is still running
  323. if ($pid)
  324. {
  325.     waitpid($pid, 0);
  326. }
  327.  
  328. exit 0;
  329.  
  330.  
  331.  
  332. sub message
  333. {
  334. local($tag, $result, $message) = @_;
  335.  
  336.     &msg'debug("message $tag $result $message");
  337.  
  338.     if ($tag eq "*")
  339.     {
  340.         MESSAGE:
  341.         {
  342.         $result =~ /OK/i && do
  343.             {
  344.                 &msg'msg("$message");
  345.                 last MESSAGE;
  346.             };
  347.         $result =~ /NO/i && do
  348.             {
  349.                 &msg'warn("$message");
  350.                 last MESSAGE;
  351.             };
  352.         $result =~ /BAD/i && do
  353.             {
  354.                 &msg'error("$message");
  355.                 last MESSAGE;
  356.             };
  357.         }
  358.     }
  359. }
  360.  
  361. sub mailbox
  362. {
  363. local($tag, $data) = @_; 
  364.  
  365.     &msg'debug("mailbox $tag $data");
  366. }
  367.  
  368. sub exists
  369. {
  370. local($tag, $result) = @_;
  371.  
  372.     &msg'debug("exists $tag $result");
  373.  
  374.     $mailbox{$mbox}->{'exists'} = $result;
  375. }
  376.  
  377. sub recent
  378. {
  379. local($tag, $result) = @_; 
  380.  
  381.     &msg'debug("recent $tag $result");
  382.  
  383.     $mailbox{$mbox}->{'recent'} = $result;
  384. }
  385.  
  386. sub expunge
  387. {
  388. local($tag, $result) = @_; 
  389.  
  390.     &msg'debug("expunge $tag $result");
  391.  
  392.     $mailbox{$mbox}->{'expunge'} = $result;
  393. }
  394.  
  395. sub fetch
  396. {
  397. local($tag, $result, $data) = @_; 
  398.  
  399.     &msg'debug("fetch $tag $result");
  400.  
  401.     if ($data =~ /RFC822\.SIZE\s+([0-9]+)/im)
  402.     {
  403.         $message{$result}->{'size'} = $1;
  404.     }
  405.     if ($data =~ /RFC822\.HEADER\s+\{([0-9]+)\}\015\012/im)
  406.     {
  407.         $message{$result}->{'header'} = substr($', 0, $1);
  408.     }
  409.     if ($data =~ /RFC822\.TEXT\s+\{([0-9]+)\}\015\012/im)
  410.     {
  411.         $message{$result}->{'text'} = substr($', 0, $1);
  412.     }
  413.     if ($data =~ /BODY\[1\]\s+\{([0-9]+)\}\015\012/im)
  414.     {
  415.         $message{$result}->{'body'} = substr($', 0, $1);
  416.     }
  417. }
  418.  
  419. sub flags
  420. {
  421. local($tag, $data) = @_; 
  422.  
  423.     &msg'debug("flags $tag $data");
  424.  
  425.     $mailbox{$mbox}->{'flags'} = $data;
  426. }
  427.  
  428. sub search
  429. {
  430. local($tag, $data) = @_; 
  431.  
  432.     &msg'debug("search $tag $data");
  433.  
  434.     $mailbox{$mbox}->{'search'} = $data;
  435. }
  436.